#include "carray.h"
#include <malloc.h>
#include <stdio.h>
#include <string.h>

#define INIT_CAP 4 //初始分配空间大小

struct _Arr {
    size_t size; //数组元素数量
    size_t capacity; //容量大小
    DATA *begpos, *endpos; //初始位置指针，末尾位置指针
};

Arr* ArrNew()
{
    Arr* p = (Arr*)malloc(sizeof(Arr));
    p->begpos = (DATA*)malloc(sizeof(DATA) * INIT_CAP); //申请 每个元素字节数*初始分配存储单元个数 大小的空间
    p->size = 0; //初始个数置为0
    p->capacity = INIT_CAP; //初始容量为默认大小
    p->endpos = p->begpos; //初始化尾指针与首指针位置相同
    return p;
}

_Bool Extend(Arr* const p)
{ //扩展数组容量大小
    DATA* newspace = (DATA*)realloc(p->begpos, sizeof(DATA) * p->capacity * 2); //申请原来空间两倍大小的空间
    if (newspace == NULL)
        return 0; //申请失败返回0
    p->begpos = newspace; //首指针指向新数组首部
    p->capacity *= 2; //容量扩大2倍
    p->endpos = p->begpos + p->size; //尾指针更新
    return 1;
}

Arr* ArrAdd(Arr* const p, const DATA value)
{ //添加新元素
    if (p->capacity == p->size) { //判断空间是否已满
        if (!Extend(p)) { //扩展新空间
            printf("%s:add %p failed! Maybe have memery not enough.\n", __func__, value);
            return NULL;
        }
    }
    *p->endpos = value; //在尾指针处放置新元素
    ++p->endpos; //尾指针后移
    ++p->size; //元素数量增加
    return p;
}

void ArrClear(Arr* const p)
{ //清空数组
    p->size = 0;
    p->endpos = p->begpos;
}

void Delete(Arr* const p)
{ //销毁数组
    free(p->begpos);
    free(p);
}

Arr* Remove(Arr* const p, const DATA aim)
{ //删除数组值为 aim 的元素
    size_t count = 0;
    DATA *w = p->begpos, *r = p->begpos; //设置两个指针初始指向首地址
    for (; r != p->endpos; ++r) { //通过两个指针移动删除某值
        if (*r == aim) {
            ++count;
            --p->size;
        } else
            *w++ = *r;
    }
    p->endpos = w;
    return p; //返回删除个数
}

Arr* Remove_if(Arr* const p, const DATA arg, _Bool (*con)(DATA, DATA))
{ //条件删除指定元素
    unsigned count = 0;
    DATA *w = p->begpos, *r = p->begpos;
    for (; r != p->endpos; ++r) {
        if (con(*r, arg)) {
            ++count;
            --p->size;
        } else
            *w++ = *r;
    }
    p->endpos = w;
    return p;
}

void ArrDeleteFake(Arr *const p)
{
    free(p);
}

void ** ArrCPtr(Arr *const p)
{
    void **ret = p->begpos;
    ArrDeleteFake(p);
    return ret;
}
